#include "tester.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#include "portable_time.h"
#include "solver_stable.h"

double f_prev(double x, double y)
{
    return 2 * (x + y) - 2 * (x * x + y * y);
}

double f(double x, double y)
{
    int n = 400;
    double hx = x / n;
    double hy = y / n;
    double cx, cy;
    
    double sum = 0.0;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cx = i * hx + 0.5 * hx;
            cy = j * hy + 0.5 * hy;
            sum += sin(exp(2 * (x + y) - 2 * (x * x + y * y)) - 1) * 
                cos(exp(2 * (x + y) - 2 * (x * x + y * y)) - 1) / 
                exp(2 * (x + y) - 2 * (x * x + y * y));
        }
    }

    return sum;
}

bool test(SolverFunc solve, int setka)
{
    bool result = true;

    Area area;
    area.a = 0.0;
    area.b = 1.0;
    area.n = setka;
    int n = area.n;
    double h = (area.b - area.a) / n;
    double eps = 0.001;
    double start, finish;

    double* u0 = new double[n * n];
    
    for (int j = 0; j < area.n; ++j)
        u0[j] = 0.0;

    //srand((unsigned int)time(NULL));
    for (int i = 1; i < n - 1; ++i)
    {
        u0[i * n] = 0.0;
        for (int j = 1; j < n - 1; ++j)
        {
            u0[i * n + j] = (double)rand() / RAND_MAX;
        }
        u0[i * n + n - 1] = 0.0;
    }

    for (int j = 0; j < area.n; ++j)
        u0[(n - 1) * n + j] = 0.0;
    
    start = PortableGetTime();
    double* u_stable = solve(u0, area, eps, f);
    finish = PortableGetTime();
    printf("Stable time: %.4f\n", finish-start);
	
    start = PortableGetTime();
    double* u = solve_stable(u0, area, eps, f);
    finish = PortableGetTime();
    printf("Current time: %.4f\n", finish-start);

    double e;
    double max_error = 0.0;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            e = abs(u[i * n + j] - u_stable[i * n + j]);
            if (e != 0)
            {
                result = false;
                if (e > max_error) max_error = e;
                break;
            }
        }

        if (result == false) break;
    }

    if (result == false)
    {
        printf("Max error: %f\n", max_error);
    }

    delete[] u0;
    delete[] u;
    delete[] u_stable;
	
    return result;
}